package com.clp.protocol.iec104.apdu.asdu.infoobj;

import com.clp.protocol.iec104.apdu.asdu.infoobj.infoelem.InfoElem;
import com.clp.protocol.iec104.apdu.asdu.infoobj.qua.Qua;
import com.clp.protocol.iec104.definition.ConstVal;
import com.clp.protocol.iec104.definition.TypeTag;
import com.clp.protocol.core.pdu.ByteToStringFormat;
import com.clp.protocol.core.pdu.nbytepdu.time2a.Time2a;
import com.clp.protocol.core.utils.ByteUtil;
import io.netty.buffer.ByteBuf;
import lombok.Getter;

import java.util.Objects;

/**
 * 文件传输的信息对象
 */
@Getter
public class FtInfoObj extends InfoObj {
    /**
     * 信息元素地址（3字节）
     */
    private int addr;
    /**
     * 信息内容
     */
    private InfoElem infoElem;

    public FtInfoObj(TypeTag typeTag) {
        super(typeTag);
    }

    public Qua getQua() {
        return null;
    }

    @Override
    public Time2a getTime2a() {
        return null;
    }

    @Override
    public FtInfoObj refreshFrom(ByteBuf buf) {
        checkTypeTag();
        // 1）、获取信息元素地址（一定有）
        byte[] bytes = new byte[ConstVal.INFO_ELEM_ADDRESS_LEN];
        buf.readBytes(bytes);
        this.addr = ByteUtil.bytes3ToIntLE(bytes);
        // 2）获取文件传输信息对象
        if (typeTag().hasInfoElem()) {
            this.infoElem = typeTag().newInvalidInfoElem().refreshFrom(buf);
        }
        return this;
    }

    @Override
    public boolean isValid() {
        if (!hasTypeTag()) return false;
        if (addr < 0) return false;
        return !typeTag().hasInfoElem() || (infoElem != null && infoElem.isValid());
    }

    @Override
    public void writeBytesTo(ByteBuf buf) {
        buf.writeBytes(ByteUtil.intToBytes3LE(addr));
        infoElem.writeBytesTo(buf);
    }

    @Override
    public void writeFormattedByteStringsTo(StringBuilder sb, String frameClipBytesSeparator, String byteSeparator, ByteToStringFormat byteFormat) {
        byte[] addrBytes = ByteUtil.intToBytes3LE(addr);
        sb.append(byteFormat.format(addrBytes[0]));
        for (int i = 1; i < addrBytes.length; i++) {
            sb.append(byteSeparator).append(addrBytes[i]);
        }
        sb.append(frameClipBytesSeparator);
        infoElem.writeFormattedByteStringsTo(sb, frameClipBytesSeparator, byteSeparator, byteFormat);
    }

    @Override
    public void writeSimpleDescriptionTo(StringBuilder sb) {
        sb.append("addr：").append(addr);
        sb.append("， infoElem："); infoElem.writeDetailDescriptionTo(sb);
    }

    @Override
    public void writeDetailDescriptionTo(StringBuilder sb) {
        sb.append("信息体地址：").append(addr);
        sb.append("， 信息内容："); infoElem.writeDetailDescriptionTo(sb);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        FtInfoObj ftInfoObj = (FtInfoObj) o;
        return addr == ftInfoObj.addr && Objects.equals(infoElem, ftInfoObj.infoElem);
    }

    @Override
    public int hashCode() {
        return Objects.hash(addr, infoElem);
    }
}
